package com.ruoyi.web.controller.business.statistics.factory;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.business.order.domain.JbOrderCommodity;
import com.ruoyi.business.rule.domain.JbLogisticsRulesJson;
import com.ruoyi.business.sundry.domain.JbProductRecipe;
import com.ruoyi.business.sundry.service.JbProductRecipeService;
import com.ruoyi.common.annotation.JoException;
import com.ruoyi.common.enums.BusinessErrorEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.controller.business.rule.factory.JbLogisticsRulesFactory;
import com.ruoyi.web.controller.business.statistics.vo.JbGrossProfitRateVO;
import com.ruoyi.web.core.JoController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 业务 统计工具 工厂
 *
 * @author Jyl
 */
@Component
public class JbGrossProfitRateFactory extends JoController
{
    private static final Logger log = LoggerFactory.getLogger(JbGrossProfitRateFactory.class);

    @Autowired
    private JbProductRecipeService jbProductRecipeService;

    @Autowired
    private JbLogisticsRulesFactory jbLogisticsRulesFactory;

    /**
     * 计算毛利率
     *
     * @param list             订单货品
     * @param id               物流主键
     * @param areaCode         地市编码
     * @param orderTotalAmount 申报金额
     * @return 毛利率计算数据
     */
    @JoException(message = "毛利率计算异常！")
    public JbGrossProfitRateVO fnGrossProfitRate(List<JbOrderCommodity> list, Long id, String areaCode,
                                                 BigDecimal orderTotalAmount)
    {
        JbGrossProfitRateVO jbGrossProfitRateVO = new JbGrossProfitRateVO();
        jbGrossProfitRateVO.setOrderTotalAmount(orderTotalAmount);
        //订单金额
        fn1(jbGrossProfitRateVO, list);
        log.info("[{}]:{}", "Order amount", jbGrossProfitRateVO);
        //库存成本
        fn2(jbGrossProfitRateVO, list);
        log.info("[{}]:{}", "Inventory cost", jbGrossProfitRateVO);
        //物流成本
        fn3(jbGrossProfitRateVO, id, areaCode);
        log.info("[{}]:{}", "Logistics cost", jbGrossProfitRateVO);
        //毛利率
        fn4(jbGrossProfitRateVO);
        log.info("[{}]:{}", "Gross profit margin", jbGrossProfitRateVO);

        return jbGrossProfitRateVO;
    }

    /**
     * 计算物流费
     *
     * @param jbGrossProfitRateVO 毛利率计算对象
     * @param logisticsRulesId    物流规则id
     * @param areaCode            地市编码
     */
    private void fn3(JbGrossProfitRateVO jbGrossProfitRateVO, Long logisticsRulesId, String areaCode)
    {
        JbLogisticsRulesJson jbLogisticsRulesJson = jbLogisticsRulesFactory.getRules(logisticsRulesId, areaCode);
        BigDecimal shippingFee = jbLogisticsRulesFactory.fnShippingFee(jbLogisticsRulesJson, jbGrossProfitRateVO);
        jbGrossProfitRateVO.setShippingFee(shippingFee.setScale(2, RoundingMode.HALF_UP));//物流成本
    }

    /**
     * 计算毛利率
     *
     * @param jbGrossProfitRateVO 毛利率计算对象
     */
    private void fn4(JbGrossProfitRateVO jbGrossProfitRateVO)
    {
        // 如果 因库存成本为空造成 毛利率为0 则跳出毛利率计算
        if (ObjectUtil.isNotEmpty(jbGrossProfitRateVO.getInventoryGrossProfitRate())
            && BigDecimal.ZERO.compareTo(jbGrossProfitRateVO.getInventoryGrossProfitRate()) == 0
        )
        {
            return;
        }

        // 获取待计算参数
        BigDecimal orderTotalAmount = jbGrossProfitRateVO.getOrderTotalAmount();//订单金额
        BigDecimal inventoryCosts = jbGrossProfitRateVO.getInventoryCosts();//库存成本
        BigDecimal realTimeCosts = jbGrossProfitRateVO.getRealTimeCosts();//实时成本
        BigDecimal shippingFee = jbGrossProfitRateVO.getShippingFee();//物流成本

        // 订单金额为0 ，不计算毛利率
        if (BigDecimal.ZERO.compareTo(orderTotalAmount) == 0)
        {
            jbGrossProfitRateVO.setInventoryGrossProfitRate(BigDecimal.ZERO);
            jbGrossProfitRateVO.setRealTimeProfitRate(BigDecimal.ZERO);
            return;
        }

        // 库存毛利率
        BigDecimal inventoryGrossProfitRate = orderTotalAmount.subtract(inventoryCosts).subtract(shippingFee);
        inventoryGrossProfitRate = inventoryGrossProfitRate.divide(orderTotalAmount, 2, RoundingMode.HALF_UP);
        jbGrossProfitRateVO.setInventoryGrossProfitRate(fnRate(inventoryGrossProfitRate));

        // 实时毛利率
        BigDecimal realTimeProfitRate = orderTotalAmount.subtract(realTimeCosts).subtract(shippingFee);
        realTimeProfitRate = realTimeProfitRate.divide(orderTotalAmount, 2, RoundingMode.HALF_UP);
        jbGrossProfitRateVO.setRealTimeProfitRate(fnRate(realTimeProfitRate));
    }

    /**
     * 换算为 百分比毛利率
     *
     * @param rate 毛利率
     * @return 格式化百分比
     */
    private BigDecimal fnRate(BigDecimal rate)
    {
        // 转百分比，最低取零，保留两位小数
        rate = rate.multiply(BigDecimal.valueOf(100));
        rate = rate.compareTo(BigDecimal.ZERO) > 0 ? rate : BigDecimal.ZERO;
        rate = rate.setScale(2, RoundingMode.HALF_UP);
        return rate;
    }

    /**
     * 获取库存成本
     *
     * @param jbGrossProfitRateVO 毛利率计算对象
     */
    private void fn2(JbGrossProfitRateVO jbGrossProfitRateVO, List<JbOrderCommodity> orderCommodities)
    {
        //查询库存数据
        LambdaQueryWrapper<JbProductRecipe> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(JbProductRecipe::getCommodityId, jbGrossProfitRateVO.getIds());
        List<JbProductRecipe> list = jbProductRecipeService.list(queryWrapper);

        BigDecimal inventoryCosts = BigDecimal.ZERO;
        BigDecimal realTimeCosts = BigDecimal.ZERO;
        BigDecimal quantity;

        Map<String, JbProductRecipe> map = new HashMap<>();
        //遍历库存商品
        for (JbProductRecipe jbProductRecipe : list)
        {
            map.put(jbProductRecipe.getCommodityId(), jbProductRecipe);
        }

        //遍历订单商品
        String commodityId;
        for (JbOrderCommodity orderCommodity : orderCommodities)
        {
            commodityId = String.valueOf(orderCommodity.getCommodityId());
            BigDecimal inventoryCost;
            BigDecimal realTimeCost;
            if (map.containsKey(commodityId))
            {
                //因用友库存成本是箱成本，
                inventoryCost = map.get(commodityId).getInventoryUnitCost();
                realTimeCost = map.get(commodityId).getRealTimeCost();
                if (ObjectUtil.isEmpty(inventoryCost))
                {
                    logger.info("毛利率计算中心 >>> >>> 因 {} 商品库存成本为空，致使毛利率为 0.00", commodityId);
                    jbGrossProfitRateVO.setInventoryGrossProfitRate(new BigDecimal("0.00"));
                    jbGrossProfitRateVO.setRealTimeProfitRate(new BigDecimal("0.00"));
                    return;
                }
                if (ObjectUtil.isEmpty(realTimeCost))
                {
                    realTimeCost = inventoryCost;
                }
            } else
            {
                throw new ServiceException(BusinessErrorEnum.LACK_OF_INVENTORY_PRICES);
            }

            quantity = orderCommodity.getQuantity();
            inventoryCosts = inventoryCosts.add(inventoryCost.multiply(quantity));
            realTimeCosts = realTimeCosts.add(realTimeCost.multiply(quantity));
        }
        jbGrossProfitRateVO.setInventoryCosts(inventoryCosts.setScale(2, RoundingMode.HALF_UP));//库存成本
        jbGrossProfitRateVO.setRealTimeCosts(realTimeCosts.setScale(2, RoundingMode.HALF_UP));//实时成本
    }

    /**
     * 整理订单数据
     *
     * @param jbGrossProfitRateVO 毛利率计算对象
     * @param list                订单货品
     */
    private void fn1(JbGrossProfitRateVO jbGrossProfitRateVO, List<JbOrderCommodity> list)
    {
//        JSONArray goods = new JSONArray();//商品
//        JSONArray giveaway = new JSONArray();//赠品
        BigDecimal orderTotalAmount = BigDecimal.ZERO;//订单金额
        BigDecimal totalAmount = BigDecimal.ZERO;//订单成本

        List<Long> ids = new ArrayList<>();//货品编码
        List<Long> goodsIds = new ArrayList<>();//商品编码
        List<Long> giveawayIds = new ArrayList<>();//赠品编码
        BigDecimal count = BigDecimal.ZERO;//货品数量
        BigDecimal unitContent = BigDecimal.ZERO;//货品重量
        BigDecimal factoryPrice = BigDecimal.ZERO;//成本价

        BigDecimal quantity;//数量
        for (JbOrderCommodity jbOrderCommodity : list)
        {
            ids.add(jbOrderCommodity.getCommodityId());

            quantity = jbOrderCommodity.getQuantity();
            count = count.add(quantity);
            unitContent = unitContent.add(jbOrderCommodity.getUnitContent().multiply(quantity));
            if (jbOrderCommodity.getType() == 0)
            {
                goodsIds.add(jbOrderCommodity.getCommodityId());
//                goods.add(jbOrderCommodity);
                orderTotalAmount = orderTotalAmount.add(jbOrderCommodity.getUnitPrice().multiply(quantity));
            } else
            {
                giveawayIds.add(jbOrderCommodity.getCommodityId());
//                giveaway.add(jbOrderCommodity);
                totalAmount = totalAmount.add(jbOrderCommodity.getUnitPrice().multiply(quantity));
            }
        }
        totalAmount = totalAmount.add(orderTotalAmount);

//        jbGrossProfitRateVO.setOrderTotalAmount(orderTotalAmount.setScale(2, RoundingMode.HALF_UP));//订单金额
        jbGrossProfitRateVO.setTotalAmount(totalAmount.setScale(2, RoundingMode.HALF_UP));//货品金额
        jbGrossProfitRateVO.setIds(ids);//货品id
        jbGrossProfitRateVO.setGoodsIds(goodsIds);//商品id
        jbGrossProfitRateVO.setGiveawayIds(giveawayIds);//赠品id
        jbGrossProfitRateVO.setCount(count.setScale(2, RoundingMode.HALF_UP));//货品数量
        jbGrossProfitRateVO.setUnitContent(unitContent.setScale(2, RoundingMode.HALF_UP));//货品重量
    }
}
